// Copyright (c) Microsoft Corporation. All rights reserved.

using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Globalization;
using System.Text;
using System.Diagnostics;

namespace Microsoft.TeamFoundation.Migration.VersionControl.Wss
{
    public class VermeerRpcResult
    {
        public VermeerRpcResult(string rpcPacket)
        {
            VermeerPacketParser parser = new VermeerPacketParser();
            parser.TitleFound += new ParserNameValueCallback(TitleFound);
            parser.ParagraphStarted += new ParserNameValueCallback(ParagraphStarted);
            parser.ParagraphFinished += new ParserNameValueCallback(ParagraphFinished);
            parser.ListStarted += new ParserCallback(ListStarted);
            parser.ListItemFound += new ParserNameValueCallback(ListItemFound);
            parser.ListFinished += new ParserCallback(ListFinished);

            m_paragraphs = new Collection<VermeerParagraph>();
            m_paragraphStack = new Stack<VermeerParagraph>();
            m_currentListStack = new Stack<VermeerList>();

            parser.Parse(rpcPacket);
        }

        public virtual Collection<VermeerParagraph> Paragraphs
        {
            get
            {
                return m_paragraphs;
            }
        }

        protected virtual void ListFinished()
        {
            m_currentListStack.Pop();
        }

        protected virtual void ListItemFound(string name, string value)
        {
            m_currentListStack.Peek().AddItem(name, value);
        }

        protected virtual void ListStarted()
        {
            string name = string.Empty;

            if (m_currentListStack.Count > 0)
            {
                VermeerList parentList = m_currentListStack.Peek();

                if (parentList.Items.Count > 0)
                {
                    name = parentList.Items[parentList.Items.Count - 1].Name;
                }
            }
            else
            {
                Debug.Assert(m_paragraphStack.Count > 0);

                VermeerParagraph currentParagraph = m_paragraphStack.Peek();
                if (currentParagraph.Lists.Count > 0)
                {
                    VermeerList latestList = currentParagraph.Lists[currentParagraph.Lists.Count - 1];
                    if (latestList.Items.Count > 0)
                    {
                        name = latestList.Items[latestList.Items.Count - 1].Name;
                    }
                }
                else
                {
                    name = currentParagraph.Name;
                }
            }

            bool isMeta = (name == "meta_info");
            VermeerList newList = new VermeerList(name, isMeta);


            if (m_currentListStack.Count > 0)
            {
                m_currentListStack.Peek().Lists.Add(newList);
            }
            else
            {
                m_paragraphStack.Peek().Lists.Add(newList);
            }

            m_currentListStack.Push(newList);
        }

        public bool IsStatusPacket
        {
            get
            {
                if (!m_isStatusPacketSet)
                {
                    bool sawMethod = false;
                    bool sawStatus = false;

                    foreach (VermeerParagraph p in Paragraphs)
                    {
                        switch (p.Name)
                        {
                            case "method":
                                sawMethod = true;
                                break;
                            case "status":
                                sawStatus = true;
                                break;
                            default:
                                break;
                        }
                    }

                    m_isStatusPacket = (sawMethod && sawStatus);

                    m_isStatusPacketSet = true;
                }

                return m_isStatusPacket;
            }
        }

        public VermeerRpcStatusResult StatusResult
        {
            get
            {
                if (IsStatusPacket && m_statusResult == null)
                {
                    m_statusResult = new VermeerRpcStatusResult(this);
                }

                return m_statusResult;
            }
        }

        protected virtual void ParagraphFinished(string name, string value)
        {
            m_paragraphStack.Pop();
        }

        protected virtual void ParagraphStarted(string name, string value)
        {
            VermeerParagraph p = new VermeerParagraph(name, value);
            m_paragraphs.Add(p);
            m_paragraphStack.Push(p);
        }

        protected virtual void TitleFound(string name, string value)
        {
            Debug.Assert(name == "title");

            if (value != s_ExpectedTitle)
            {
                throw new FPRpcException(
                    string.Format(CultureInfo.InvariantCulture, "Unexpected packet title: \"{0}\"", value));
            }
        }


        Collection<VermeerParagraph> m_paragraphs;
        Stack<VermeerParagraph> m_paragraphStack;
        Stack<VermeerList> m_currentListStack;

        bool m_isStatusPacketSet;
        bool m_isStatusPacket = true;
        VermeerRpcStatusResult m_statusResult;

        const string s_ExpectedTitle = "vermeer RPC packet";
    }
}
